import BasePlugin from './BasePlugin';

/**
 * 对齐插件 - 处理对象对齐
 */
export default class AlignmentPlugin extends BasePlugin {
    constructor() {
        super();
        this.alignmentLines = [];
        this.showAlignmentLines = true;
        this.alignmentLineColor = '#0099ff';
        this.alignmentLineWidth = 1;
        this.alignmentThreshold = 5;
    }

    /**
     * 初始化插件
     */
    init(editor) {
        super.init(editor);
        this._setupEventListeners();
    }

    /**
     * 启用对齐功能
     */
    enable() {
        super.enable();
        this.showAlignmentLines = true;
    }

    /**
     * 禁用对齐功能
     */
    disable() {
        super.disable();
        this.showAlignmentLines = false;
        this._clearAlignmentLines();
    }

    /**
     * 左对齐
     */
    alignLeft() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 2) return;

        const minLeft = Math.min(...objects.map(obj => obj.left));
        objects.forEach(obj => {
            obj.set('left', minLeft);
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('left');
    }

    /**
     * 右对齐
     */
    alignRight() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 2) return;

        const maxRight = Math.max(...objects.map(obj => obj.left + obj.getScaledWidth()));
        objects.forEach(obj => {
            obj.set('left', maxRight - obj.getScaledWidth());
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('right');
    }

    /**
     * 顶部对齐
     */
    alignTop() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 2) return;

        const minTop = Math.min(...objects.map(obj => obj.top));
        objects.forEach(obj => {
            obj.set('top', minTop);
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('top');
    }

    /**
     * 底部对齐
     */
    alignBottom() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 2) return;

        const maxBottom = Math.max(...objects.map(obj => obj.top + obj.getScaledHeight()));
        objects.forEach(obj => {
            obj.set('top', maxBottom - obj.getScaledHeight());
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('bottom');
    }

    /**
     * 水平居中对齐
     */
    alignHorizontalCenter() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 2) return;

        const centerX = this._getSelectionCenterX(objects);
        objects.forEach(obj => {
            obj.set('left', centerX - obj.getScaledWidth() / 2);
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('horizontalCenter');
    }

    /**
     * 垂直居中对齐
     */
    alignVerticalCenter() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 2) return;

        const centerY = this._getSelectionCenterY(objects);
        objects.forEach(obj => {
            obj.set('top', centerY - obj.getScaledHeight() / 2);
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('verticalCenter');
    }

    /**
     * 水平分布
     */
    distributeHorizontally() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 3) return;

        // 按左边界排序
        const sortedObjects = [...objects].sort((a, b) => a.left - b.left);
        const firstObj = sortedObjects[0];
        const lastObj = sortedObjects[sortedObjects.length - 1];
        const totalWidth = lastObj.left + lastObj.getScaledWidth() - firstObj.left;
        const spacing = (totalWidth - objects.reduce((sum, obj) => sum + obj.getScaledWidth(), 0)) / (objects.length - 1);

        let currentLeft = firstObj.left;
        sortedObjects.forEach((obj, index) => {
            if (index > 0 && index < sortedObjects.length - 1) {
                obj.set('left', currentLeft + spacing);
            }
            currentLeft = obj.left + obj.getScaledWidth();
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('distributeHorizontally');
    }

    /**
     * 垂直分布
     */
    distributeVertically() {
        if (!this.isEnabled() || !this.canvas) return;

        const objects = this._getSelectedObjects();
        if (objects.length < 3) return;

        // 按顶边界排序
        const sortedObjects = [...objects].sort((a, b) => a.top - b.top);
        const firstObj = sortedObjects[0];
        const lastObj = sortedObjects[sortedObjects.length - 1];
        const totalHeight = lastObj.top + lastObj.getScaledHeight() - firstObj.top;
        const spacing = (totalHeight - objects.reduce((sum, obj) => sum + obj.getScaledHeight(), 0)) / (objects.length - 1);

        let currentTop = firstObj.top;
        sortedObjects.forEach((obj, index) => {
            if (index > 0 && index < sortedObjects.length - 1) {
                obj.set('top', currentTop + spacing);
            }
            currentTop = obj.top + obj.getScaledHeight();
        });

        this.canvas.renderAll();
        this._emitAlignmentEvent('distributeVertically');
    }

    /**
     * 获取选中对象
     */
    _getSelectedObjects() {
        const activeObject = this.canvas.getActiveObject();
        return activeObject && activeObject.type === 'activeSelection'
            ? activeObject.getObjects()
            : [activeObject];
    }

    /**
     * 获取选区水平中心点
     */
    _getSelectionCenterX(objects) {
        const bounds = this._getSelectionBounds(objects);
        return bounds.left + bounds.width / 2;
    }

    /**
     * 获取选区垂直中心点
     */
    _getSelectionCenterY(objects) {
        const bounds = this._getSelectionBounds(objects);
        return bounds.top + bounds.height / 2;
    }

    /**
     * 获取选区边界
     */
    _getSelectionBounds(objects) {
        const coords = objects.map(obj => ({
            left: obj.left,
            top: obj.top,
            right: obj.left + obj.getScaledWidth(),
            bottom: obj.top + obj.getScaledHeight()
        }));

        return {
            left: Math.min(...coords.map(c => c.left)),
            top: Math.min(...coords.map(c => c.top)),
            width: Math.max(...coords.map(c => c.right)) - Math.min(...coords.map(c => c.left)),
            height: Math.max(...coords.map(c => c.bottom)) - Math.min(...coords.map(c => c.top))
        };
    }

    /**
     * 显示对齐线
     */
    _showAlignmentLines(lines) {
        this._clearAlignmentLines();

        lines.forEach(line => {
            const alignmentLine = new fabric.Line(line, {
                stroke: this.alignmentLineColor,
                strokeWidth: this.alignmentLineWidth,
                selectable: false,
                evented: false,
                strokeDashArray: [5, 5]
            });

            this.alignmentLines.push(alignmentLine);
            this.canvas.add(alignmentLine);
        });

        this.canvas.renderAll();
    }

    /**
     * 清除对齐线
     */
    _clearAlignmentLines() {
        this.alignmentLines.forEach(line => {
            this.canvas.remove(line);
        });
        this.alignmentLines = [];
        this.canvas.renderAll();
    }

    /**
     * 发送对齐事件
     */
    _emitAlignmentEvent(type) {
        this.editor.emit('alignment:applied', {
            type,
            objects: this._getSelectedObjects()
        });
    }

    /**
     * 设置事件监听
     */
    _setupEventListeners() {
        if (!this.canvas) return;

        // 监听对象移动事件
        this.canvas.on('object:moving', (e) => {
            if (!this.isEnabled() || !this.showAlignmentLines) return;

            const movingObject = e.target;
            const allObjects = this.canvas.getObjects().filter(obj =>
                obj !== movingObject &&
                obj.type !== 'line' &&
                !this.alignmentLines.includes(obj)
            );

            const alignmentLines = [];

            allObjects.forEach(obj => {
                // 水平对齐
                if (Math.abs(movingObject.left - obj.left) < this.alignmentThreshold) {
                    // 左对齐
                    movingObject.set('left', obj.left);
                    alignmentLines.push([obj.left, 0, obj.left, this.canvas.height]);
                }
                if (Math.abs((movingObject.left + movingObject.getScaledWidth()) - (obj.left + obj.getScaledWidth())) < this.alignmentThreshold) {
                    // 右对齐
                    movingObject.set('left', obj.left + obj.getScaledWidth() - movingObject.getScaledWidth());
                    alignmentLines.push([obj.left + obj.getScaledWidth(), 0, obj.left + obj.getScaledWidth(), this.canvas.height]);
                }

                // 垂直对齐
                if (Math.abs(movingObject.top - obj.top) < this.alignmentThreshold) {
                    // 顶部对齐
                    movingObject.set('top', obj.top);
                    alignmentLines.push([0, obj.top, this.canvas.width, obj.top]);
                }
                if (Math.abs((movingObject.top + movingObject.getScaledHeight()) - (obj.top + obj.getScaledHeight())) < this.alignmentThreshold) {
                    // 底部对齐
                    movingObject.set('top', obj.top + obj.getScaledHeight() - movingObject.getScaledHeight());
                    alignmentLines.push([0, obj.top + obj.getScaledHeight(), this.canvas.width, obj.top + obj.getScaledHeight()]);
                }
            });

            if (alignmentLines.length > 0) {
                this._showAlignmentLines(alignmentLines);
            } else {
                this._clearAlignmentLines();
            }
        });

        // 监听对象移动结束事件
        this.canvas.on('object:modified', () => {
            this._clearAlignmentLines();
        });
    }

    /**
     * 销毁插件
     */
    destroy() {
        if (this.canvas) {
            this._clearAlignmentLines();
        }
        super.destroy();
    }
} 